<?php
declare (strict_types = 1);

namespace app\middleware;

use think\facade\Request;
use think\facade\Db;
use think\facade\Config;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

/**
 * 数据权限控制中间件
 * 实现多维度数据权限验证：
 * 1. 个人数据权限 (belong_uid) - 用户只能查看/操作自己创建的数据
 * 2. 部门数据权限 (belong_did) - 用户可以查看/操作本部门或下级部门的数据
 * 3. 数据共享权限 (share_ids) - 用户可以查看/操作共享给自己的数据
 * 4. 审批数据权限 (check_uids) - 用户可以查看/操作需要自己审批的数据
 */
class DataPermission
{
    /**
     * 处理请求
     * @param \think\Request $request
     * @param \Closure $next
     * @return mixed
     */
    public function handle($request, \Closure $next)
    {
        // 获取当前用户信息
        $userId = $this->getUserId($request);
        $userInfo = $this->getUserInfo($userId);
        
        if ($userId > 0 && $userInfo) {
            // 记录调试信息
            \think\facade\Log::info('DataPermission中间件设置用户信息', [
                'userId' => $userId,
                'has_user_info' => !empty($userInfo),
                'user_department' => $userInfo['did'] ?? 0
            ]);
            
            // 直接将用户信息和权限信息设置到请求对象的属性中
            $request->dataUserId = $userId;
            $request->dataUserInfo = $userInfo;
            $request->dataPermissions = $this->buildDataPermissions($userInfo);
        }
        
        return $next($request);
    }
    
    /**
     * 获取当前登录用户ID
     * @param \think\Request $request
     * @return int
     */
    private function getUserId($request)
    {
        // 首先尝试从Authorization头获取JWT token
        $authHeader = $request->header('Authorization');
        if ($authHeader) {
            $token = str_replace('Bearer ', '', $authHeader);
            $userId = $this->verifyJwtToken($token);
            if ($userId) {
                return $userId;
            }
        }
        
        // 如果JWT验证失败，尝试从Token参数获取
        $token = $request->param('token') ?: $request->header('Token');
        if ($token) {
            return $this->verifyJwtToken($token);
        }
        
        return 0;
    }
    
    /**
     * 验证JWT token
     * @param string $token JWT token
     * @return int|false 用户ID或false
     */
    private function verifyJwtToken($token)
    {
        try {
            if (empty($token)) {
                return false;
            }
            
            // 使用统一的JWT配置
            $jwtConfig = Config::get('jwt');
            if (!$jwtConfig || !isset($jwtConfig['key'])) {
                return false;
            }
            
            // 设置时间容差
            JWT::$leeway = 60;
            
            // 解码JWT
            $decoded = JWT::decode($token, new Key($jwtConfig['key'], $jwtConfig['algorithm'] ?? 'HS256'));
            $decoded_array = json_decode(json_encode($decoded), true);
            
            // 检查过期时间
            if (isset($decoded_array['exp']) && $decoded_array['exp'] < time()) {
                return false;
            }
            
            // 兼容新的JWT格式（sub字段）和原系统格式（data.userid字段）
            if (isset($decoded_array['sub'])) {
                return (int)$decoded_array['sub'];
            } elseif (isset($decoded_array['data']['userid'])) {
                return (int)$decoded_array['data']['userid'];
            }
            
            return false;
        } catch (\Exception $e) {
            return false;
        }
    }
    
    /**
     * 获取用户详细信息
     * @param int $userId
     * @return array|false
     */
    private function getUserInfo($userId)
    {
        if ($userId <= 0) {
            return false;
        }
        
        try {
            // 获取用户基本信息
            $user = Db::name('admin')->where('id', $userId)->find();
            if (!$user) {
                return false;
            }
            
            // 获取用户部门信息
            $department = null;
            if ($user['did'] > 0) {
                $department = Db::name('department')->where('id', $user['did'])->find();
            }
            
            // 获取用户职位信息
            $position = null;
            if ($user['position_id'] > 0) {
                $position = Db::name('position')->where('id', $user['position_id'])->find();
            }
            
            return [
                'id' => $user['id'],
                'username' => $user['username'],
                'name' => $user['name'],
                'did' => $user['did'],
                'position_id' => $user['position_id'],
                'status' => $user['status'],
                'department' => $department,
                'position' => $position,
                'is_super_admin' => $user['id'] == 1
            ];
        } catch (\Exception $e) {
            return false;
        }
    }
    
    /**
     * 构建数据权限规则
     * @param array $userInfo
     * @return array
     */
    private function buildDataPermissions($userInfo)
    {
        $permissions = [
            'user_id' => $userInfo['id'],
            'department_id' => $userInfo['did'],
            'position_id' => $userInfo['position_id'],
            'is_super_admin' => $userInfo['is_super_admin'],
            'leader_departments' => [], // 用户作为领导的部门ID列表
            'subordinate_departments' => [], // 用户管理的下级部门ID列表
        ];
        
        // 超级管理员拥有所有权限
        if ($userInfo['is_super_admin']) {
            $permissions['has_all_permission'] = true;
            return $permissions;
        }
        
        try {
            // 获取用户作为领导的部门
            $permissions['leader_departments'] = $this->getLeaderDepartments($userInfo['id']);
            
            // 获取用户管理的下级部门
            $permissions['subordinate_departments'] = $this->getSubordinateDepartments($userInfo['did']);
            
        } catch (\Exception $e) {
            // 权限查询失败，但不影响正常流程
        }
        
        return $permissions;
    }
    
    /**
     * 获取用户作为领导的部门ID列表
     * @param int $userId
     * @return array
     */
    private function getLeaderDepartments($userId)
    {
        try {
            // 查询用户作为领导的部门
            $leaderDepts = Db::name('department')
                ->where('leader_id', $userId)
                ->column('id');
            
            return array_map('intval', $leaderDepts ?: []);
        } catch (\Exception $e) {
            return [];
        }
    }
    
    /**
     * 获取下级部门ID列表（递归）
     * @param int $departmentId
     * @return array
     */
    private function getSubordinateDepartments($departmentId)
    {
        if ($departmentId <= 0) {
            return [];
        }
        
        try {
            // 获取直接下级部门
            $childDepts = Db::name('department')
                ->where('pid', $departmentId)
                ->column('id');
            
            $result = array_map('intval', $childDepts ?: []);
            
            // 递归获取下级部门的下级部门
            foreach ($childDepts as $childId) {
                $subDepts = $this->getSubordinateDepartments($childId);
                $result = array_merge($result, $subDepts);
            }
            
            return array_unique($result);
        } catch (\Exception $e) {
            return [];
        }
    }
}